import numpy as np
from sklearn import metrics
from sklearn.cluster import SpectralCoclustering, KMeans, AffinityPropagation
import matplotlib.pyplot as plt

'''
random_state（随机状态）,作用：控制随机状态。
'''
def my_SpectralCoclustering(pearson, n_clusters=300):
    X = np.array(pearson)
    #print(X.shape)
    model=SpectralCoclustering(n_clusters=n_clusters)
    clustering = model.fit(X)  # , random_state=0
    print("聚类簇结果索引：")
    print(clustering.row_labels_)
    lunkuo=metrics.silhouette_score(X,clustering.row_labels_,metric='cosine')
    print("轮廓系数："+str(lunkuo))

    #print("每个轮廓系数："+str((metrics.silhouette_samples(X, clustering.row_labels_, metric='cosine'))))

    fit_data=X[np.argsort(model.row_labels_)]
    fit_data=fit_data[:,np.argsort(model.column_labels_)]
    plt.matshow(fit_data,cmap=plt.cm.Blues)
    plt.title("After biclustering")
    plt.show()


    #删除轮廓系数负数
    stack=Stack()
    list=metrics.silhouette_samples(X, clustering.row_labels_, metric='cosine')
    for index,li in enumerate(list):
        if li<0.0 :
            stack.push(index)
    while(stack.isEmpty()==False):
        index=stack.pop()
        np.delete(X,index,axis=0)
        np.delete(X, index, axis=1)

    model = SpectralCoclustering(n_clusters=n_clusters-2)
    clustering = model.fit(X)  # , random_state=0
    print("聚类簇结果索引：")
    print(clustering.row_labels_)
    fit_data=X[np.argsort(model.row_labels_)]
    fit_data=fit_data[:,np.argsort(model.column_labels_)]
    plt.matshow(fit_data,cmap=plt.cm.Blues)
    plt.title("delete negative Silhouette")
    plt.show()



    return clustering.row_labels_



def my_AffinityPropagation(pearson):
    X = np.array(pearson)
    # X = np.array([[1, 2], [1, 4], [1, 0], [4, 2], [4, 4], [4, 0]])
    clustering = AffinityPropagation(preference=-50, random_state=5).fit(X)
    print(clustering.labels_)
    return clustering.labels_


def my_kmeans(pearson, n_clusters=3):
    X = np.array(pearson)
    clustering = KMeans(n_clusters).fit(X)
    print(clustering.row_labels_)


def zhoubu(x):
    # x代表需要聚类数据的坐标

    Sum = np.zeros(323)  # Sum用于储存肘部法则判断指标
    for i in range(2, 325):
        kmeans = KMeans(n_clusters=i).fit(x)  # kmeans算法拟合
        m = kmeans.labels_  # 取出分类得出的标签
        c = kmeans.cluster_centers_  # 取出每个分类中心
        for j in range(len(x)):
            c1 = c[m[j]]  # 第j个样本所属类的中心
            x1 = x[j]  # 第j个样本的坐标
            Sum[i - 2] = Sum[i - 2] + sum((x1 - c1) ** 2)  # 计算判断指标
    c = plt.plot(np.arange(2, 325), Sum)
    plt.xticks(np.arange(2, 325))  # 绘图
    plt.show()
    return Sum


class Stack:
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return self.items == []
    def push(self, item):
        self.items.append(item)
    def pop(self):
        return self.items.pop()
    def peek(self):
        return self.items[len(self.items)-1]
    def size(self):
        return len(self.items)